home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / TCL1 / MIDI_MAN / CMIDIOUT.C < prev    next >
Text File  |  1992-03-07  |  6KB  |  163 lines

  1. //--- CMIDIOutputPort.c ----------------------------------------------------------------
  2. // Copyright ⌐ Paul Ferguson, 1990, 1991, 1992.  All rights reserved.
  3. //
  4. // Superclass:  CDataPort
  5. // Subclasses:  None
  6. //
  7. // Description:
  8. //    CMIDIOutputPort.c defines a MIDI Manager port object.
  9. //
  10. //    For use with THINK C 5.0, the accompanying THINK Class Library (TCL), and MIDI
  11. //    Manager 2.0. Refer to the accompanying Microsoft Word document for complete
  12. //    details about MIDI Manager objects.
  13. //
  14. //    If you have comments or questions about this code, you can reach me on
  15. //    CompuServe at 70441,3055.
  16. //
  17. //--------------------------------------------------------------------------------------
  18. //---- NOTE --- NOTE --- NOTE --- NOTE --- NOTE --- NOTE --- NOTE --- NOTE --- NOTE ----
  19. //--------------------------------------------------------------------------------------
  20. //    If you are not familiar with programming the Apple MIDI Manager, refer to the
  21. //    "MIDI Management Tools" Version 2.0, available from APDA.  You MUST have the
  22. //    software (MIDI.H and the library) from this package in order to use these objects.
  23. //    It will not work without this.
  24. //--------------------------------------------------------------------------------------
  25. //    REVISION HISTORY:
  26. //        August ??, 1990            - Original release (1.0).
  27. //        November 5, 1990        - Added checks for midiMgrVer to most methods.
  28. //        August 1991                - updated for THINK C 5.0 as version 2.0
  29. //--------------------------------------------------------------------------------------
  30.  
  31. #include "CMIDIOutputPort.h"                // This code's header file
  32.  
  33. extern    OSType            gSignature;            // Used to register client
  34. #define noClient        '    '                // The UnClient
  35.  
  36. extern CMIDIClient * gMIDIClient;
  37.  
  38. OSErr CMIDIOutputPort::IMIDIOutputPort(StringPtr        theName,
  39.                                        OSType            thePortID,
  40.                                        Boolean            theVisibleFlag,
  41.                                        CMIDITimePort *    theTimePort,
  42.                                        long                theOffset)
  43. {
  44.     MIDIPortParams                portParams;    // MIDI Mgr Init data structure
  45.     register MIDIPortParams *    portPPtr = &portParams;
  46.  
  47.     portPPtr->portID            = thePortID;
  48.     portPPtr->portType            = midiPortTypeOutput;
  49.     if ( (theVisibleFlag == FALSE) && (itsVersion >= 0x0200) )    // Invisible output port, in 2.x
  50.         portPPtr->portType        |= midiPortInvisible;
  51.  
  52.     portPPtr->timeBase            = theTimePort ? theTimePort->GetRefNum() : 0;
  53.     portPPtr->offsetTime        = theOffset;
  54.     portPPtr->readHook            = (Ptr) 0;
  55.     portPPtr->refCon            = SetCurrentA5();
  56.     BlockMove(theName, portPPtr->name, theName[0]+1);
  57.     return IMIDIPort(portPPtr, 0);
  58. }
  59.  
  60. OSErr CMIDIOutputPort::WritePacket(MIDIPacketPtr theMIDIPacket)
  61. {
  62.     return itsVersion ? MIDIWritePacket(itsRefNum, theMIDIPacket) : ErrNoMIDI;
  63. }
  64.  
  65. //--- CMIDIOutputPort::Write ----------------------------------------------
  66. // Send a packet immediately without timestamp.
  67. //-------------------------------------------------------------------------
  68.  
  69. OSErr CMIDIOutputPort::Write(char * theData, short theDataLen)
  70. {
  71.     return DoMIDIWrite(theData, theDataLen, midiTimeStampCurrent, 0);
  72. }
  73.  
  74. //--- CMIDIOutputPort::WriteTS --------------------------------------------
  75. // Send a packet immediately with the user-supplied timestamp.
  76. //-------------------------------------------------------------------------
  77.  
  78. OSErr CMIDIOutputPort::WriteTS(char * theData, short theDataLen, long theTimeStamp)
  79. {
  80.     return DoMIDIWrite(theData, theDataLen, midiTimeStampValid, theTimeStamp);
  81. }
  82.  
  83.  
  84. //--- CMIDIOutputPort::DoMIDIWrite --------------------------------------------
  85. // This local function does all the real work of sending MIDI data.
  86. //
  87. // This method is classified as 'private' in CMIDI.h.  If you wish to call
  88. // this method directly, simply change the header file.
  89. //
  90. // If you know your application is going to write a lot of short or fixed
  91. // length packets, you may wish to override or modify this method to remove the
  92. // BlockMove trap and multi-length packet logic overhead.
  93. //
  94. // It is called by CMIDIOutputPort::Write() and CMIDIOutputPort::WriteTS().
  95. //-----------------------------------------------------------------------------
  96.  
  97. OSErr CMIDIOutputPort::DoMIDIWrite(    char *            theData,
  98.                                     short            theDataLen,
  99.                                     unsigned char    theFlags,
  100.                                     long            theTimeStamp)
  101. {
  102.     MIDIPacket                midiPacket;        // MIDI Manager packet to be transmitted
  103.     register MIDIPacketPtr    midiPPtr = &midiPacket;
  104.     
  105.     if (itsVersion == 0) return (ErrNoMIDI);
  106.     
  107.     if (theDataLen < 250)    // Handle short packets directly
  108.     {
  109.         midiPPtr->flags = theFlags | midiMsgType | midiNoCont;
  110.         midiPPtr->len   = theDataLen + 6;
  111.         if (theFlags == midiTimeStampValid)
  112.             midiPPtr->tStamp = theTimeStamp;
  113.         BlockMove(theData, &(midiPPtr->data[0]), theDataLen);
  114.         return MIDIWritePacket(itsRefNum, &midiPacket);
  115.     }
  116.     else                    // Multiple packet send    (more than 249 bytes)
  117.     {
  118.         register char *    source = theData;
  119.         register short    thisPacketLen;
  120.         OSErr            err;
  121.  
  122.         do
  123.         {
  124.             midiPPtr->flags  = theFlags | midiMsgType;            // Re-init each time
  125.             if (theFlags == midiTimeStampValid)
  126.                 midiPPtr->tStamp = theTimeStamp;
  127.             thisPacketLen = (theDataLen < 249) ? theDataLen : 249;
  128.             BlockMove(source, &(midiPPtr->data[0]), thisPacketLen);// Data to write
  129.             /*
  130.              * Set the continuation bits field in the flags byte.
  131.              */
  132.             theDataLen -= thisPacketLen;
  133.             if (source == theData)                            // the first piece of the message
  134.             {
  135.                 if (theDataLen > 0)                            // Multiple writes required?
  136.                     midiPPtr->flags |= midiStartCont;        // Yes
  137.                 else                                        // Everything fits in one packet
  138.                     midiPPtr->flags |= midiNoCont;            // SHOULD NEVER SEE THIS CASE HERE!
  139.             }
  140.             else
  141.             {
  142.                 if (theDataLen > 0)                            // a middle piece
  143.                     midiPPtr->flags |= midiMidCont;
  144.                 else                                        // Last piece of the message
  145.                     midiPPtr->flags |= midiEndCont;
  146.             }
  147.             midiPPtr->len = thisPacketLen + 6;                // Set the packet length
  148.             err = MIDIWritePacket(itsRefNum, midiPPtr);        // ÑÑÑ Call MIDI Manager
  149.             if (err) break;
  150.  
  151. // You may want to add more sophisticated error handling here.  Also, if you are
  152. // sending large packets like system exclusive messages, you may need to add a
  153. // timing delay here so you don't overflow the output buffer or the device.
  154.  
  155.             source += thisPacketLen;                        // Bump pointer
  156.  
  157.         } while (theDataLen > 0);        // Loop for next portion of data
  158.         return err;                        // Indicates last result
  159.     }
  160. }
  161.  
  162. // end of CMIDIOutputPort.c
  163.